1   /*
2    * Copyright (C) 2008 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.testing;
18  
19  import com.google.common.annotations.GwtCompatible;
20  import com.google.common.annotations.GwtIncompatible;
21  
22  import junit.framework.TestCase;
23  
24  import java.util.EnumSet;
25  import java.util.concurrent.Callable;
26  import java.util.concurrent.CountDownLatch;
27  import java.util.concurrent.ExecutorService;
28  import java.util.concurrent.Executors;
29  import java.util.concurrent.TimeUnit;
30  
31  /**
32   * Unit test for {@link FakeTicker}.
33   *
34   * @author Jige Yu
35   */
36  @GwtCompatible(emulated = true)
37  public class FakeTickerTest extends TestCase {
38  
39    @GwtIncompatible("NullPointerTester")
40    public void testNullPointerExceptions() {
41      NullPointerTester tester = new NullPointerTester();
42      tester.testAllPublicInstanceMethods(new FakeTicker());
43    }
44  
45    public void testAdvance() {
46      FakeTicker ticker = new FakeTicker();
47      assertEquals(0, ticker.read());
48      assertSame(ticker, ticker.advance(10));
49      assertEquals(10, ticker.read());
50      ticker.advance(1, TimeUnit.MILLISECONDS);
51      assertEquals(1000010L, ticker.read());
52    }
53  
54    public void testAutoIncrementStep_returnsSameInstance() {
55      FakeTicker ticker = new FakeTicker();
56      assertSame(ticker, ticker.setAutoIncrementStep(10, TimeUnit.NANOSECONDS));
57    }
58  
59    public void testAutoIncrementStep_nanos() {
60      FakeTicker ticker = new FakeTicker().setAutoIncrementStep(10, TimeUnit.NANOSECONDS);
61      assertEquals(0, ticker.read());
62      assertEquals(10, ticker.read());
63      assertEquals(20, ticker.read());
64    }
65  
66    public void testAutoIncrementStep_millis() {
67      FakeTicker ticker = new FakeTicker().setAutoIncrementStep(1, TimeUnit.MILLISECONDS);
68      assertEquals(0, ticker.read());
69      assertEquals(1000000, ticker.read());
70      assertEquals(2000000, ticker.read());
71    }
72  
73    public void testAutoIncrementStep_seconds() {
74      FakeTicker ticker = new FakeTicker().setAutoIncrementStep(3, TimeUnit.SECONDS);
75      assertEquals(0, ticker.read());
76      assertEquals(3000000000L, ticker.read());
77      assertEquals(6000000000L, ticker.read());
78    }
79  
80    public void testAutoIncrementStep_resetToZero() {
81      FakeTicker ticker = new FakeTicker().setAutoIncrementStep(10, TimeUnit.NANOSECONDS);
82      assertEquals(0, ticker.read());
83      assertEquals(10, ticker.read());
84      assertEquals(20, ticker.read());
85  
86      for (TimeUnit timeUnit : EnumSet.allOf(TimeUnit.class)) {
87        ticker.setAutoIncrementStep(0, timeUnit);
88        assertEquals(
89            "Expected no auto-increment when setting autoIncrementStep to 0 " + timeUnit,
90            30, ticker.read());
91      }
92    }
93  
94    public void testAutoIncrement_negative() {
95      FakeTicker ticker = new FakeTicker();
96      try {
97        ticker.setAutoIncrementStep(-1, TimeUnit.NANOSECONDS);
98        fail("Expected IllegalArgumentException");
99      } catch (IllegalArgumentException expected) {
100     }
101   }
102 
103   @GwtIncompatible("concurrency")
104 
105   public void testConcurrentAdvance() throws Exception {
106     final FakeTicker ticker = new FakeTicker();
107 
108     int numberOfThreads = 64;
109     runConcurrentTest(numberOfThreads,
110         new Callable<Void>() {
111           @Override
112           public Void call() throws Exception {
113             // adds two nanoseconds to the ticker
114             ticker.advance(1L);
115             Thread.sleep(10);
116             ticker.advance(1L);
117             return null;
118           }
119         });
120 
121     assertEquals(numberOfThreads * 2, ticker.read());
122   }
123 
124   @GwtIncompatible("concurrency")
125 
126   public void testConcurrentAutoIncrementStep() throws Exception {
127     int incrementByNanos = 3;
128     final FakeTicker ticker =
129         new FakeTicker().setAutoIncrementStep(incrementByNanos, TimeUnit.NANOSECONDS);
130 
131     int numberOfThreads = 64;
132     runConcurrentTest(numberOfThreads,
133         new Callable<Void>() {
134           @Override
135           public Void call() throws Exception {
136             ticker.read();
137             return null;
138           }
139         });
140 
141     assertEquals(incrementByNanos * numberOfThreads, ticker.read());
142   }
143 
144   /**
145    * Runs {@code callable} concurrently {@code numberOfThreads} times.
146    */
147   @GwtIncompatible("concurrency")
148   private void runConcurrentTest(int numberOfThreads, final Callable<Void> callable)
149       throws Exception {
150     ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
151     final CountDownLatch startLatch = new CountDownLatch(numberOfThreads);
152     final CountDownLatch doneLatch = new CountDownLatch(numberOfThreads);
153     for (int i = numberOfThreads; i > 0; i--) {
154       executorService.submit(new Callable<Void>() {
155         @Override
156         public Void call() throws Exception {
157           startLatch.countDown();
158           startLatch.await();
159           callable.call();
160           doneLatch.countDown();
161           return null;
162         }
163       });
164     }
165     doneLatch.await();
166   }
167 }